package me.firstapp.service.weixin.cash.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import me.firstapp.common.exception.ServiceException;
import me.firstapp.common.exception.StatusHouse;
import me.firstapp.common.utils.DateUtils;
import me.firstapp.common.utils.MD5Utils;
import me.firstapp.common.utils.Page;
import me.firstapp.common.utils.StrUtils;
import me.firstapp.module.weixin.cash.CashApply;
import me.firstapp.module.weixin.jinbi.JinBiAccount;
import me.firstapp.module.weixin.jinbi.JinBiAccountTrace;
import me.firstapp.module.weixin.jinbi.JinBiAccountTrace.ChangeType;
import me.firstapp.module.weixin.member.Member;
import me.firstapp.module.weixin.system.ThisSystem;
import me.firstapp.repository.weixin.cash.CashApplyRepository;
import me.firstapp.repository.weixin.jinbi.JinBiAccountRepository;
import me.firstapp.repository.weixin.jinbi.JinBiAccountTraceRepository;
import me.firstapp.repository.weixin.member.MemberRepository;
import me.firstapp.repository.weixin.system.ThisSystemRepository;
import me.firstapp.service.weixin.cash.CashApplyService;

@Service
public class CashApplyServiceImpl implements CashApplyService {

	@Autowired
	private MemberRepository memberRepository;

	@Autowired
	private CashApplyRepository cashApplyRepository;

	@Autowired
	private JinBiAccountRepository jinBiAccountRepository;

	@Autowired
	private JinBiAccountTraceRepository jinBiAccountTraceRepository;

	@Autowired
	private ThisSystemRepository thisSystemRepository;

	@Override
	public CashApply executeAddCashApply(String openId, String contact, String realName, String aliAccount) {
		Member member = memberRepository.findMemberByOpenId(openId);
		if (null == member) {
			throw new ServiceException(StatusHouse.STATUS_MEMBER_NOT_EXIST);
		}
		if (Member.STATUS_NO_USE == member.getStatus()) {
			throw new ServiceException(StatusHouse.STATUS_MEMBER_NO_USE_ERROR);
		}
		if (Member.FOLLOW_STATUS_NO == member.getFollowStatus()) {
			throw new ServiceException(StatusHouse.STATUS_PAGE_ERROR_NOT_CONCERN_WEIXIN);
		}

		JinBiAccount jinBiAccount = jinBiAccountRepository.findJinBiAccountByCardNoAndOpenId(member.getCardNo(),
				openId);
		boolean isNormal = MD5Utils.verify(jinBiAccount.getBalance().doubleValue() * 10000 + "",
				jinBiAccount.getEncryption());
		if (!isNormal) {
			throw new ServiceException(StatusHouse.STATUS_ACCOUNT_NOT_NORMAL_ERROR);
		}
		int a = (int) (jinBiAccount.getBalance().doubleValue() / 100 * 100);
		int b = a % 100;
		int money = a - b;
		if (money < 100) {
			throw new ServiceException(StatusHouse.STATUS_BALANCE_NOT_ENOUGH_ERROR);
		}

		JinBiAccountTrace jinBiAccountTrace = new JinBiAccountTrace();
		jinBiAccountTrace.setJinBiAccountId(jinBiAccount.getId());
		jinBiAccountTrace.setChangeType(ChangeType.JINBI_SUB_CASH);
		jinBiAccountTrace.setBeforeValue(jinBiAccount.getBalance());
		jinBiAccountTrace.setChangeValue(new BigDecimal(money));
		BigDecimal afterValue = jinBiAccount.getBalance().subtract(new BigDecimal(money));
		jinBiAccountTrace.setAfterValue(afterValue);
		jinBiAccountTrace.setChangeTime(new Date());
		jinBiAccountTrace.setChangeDate(Integer.valueOf(DateUtils.getDateStr(new Date(), "yyyyMMdd")));
		jinBiAccountTraceRepository.save(jinBiAccountTrace);

		jinBiAccount.setBalance(afterValue);
		jinBiAccount.setUpdateTime(new Date());
		jinBiAccount.setEncryption(MD5Utils.generate(jinBiAccount.getBalance().doubleValue() * 10000 + ""));
		jinBiAccountRepository.update(jinBiAccount);

		ThisSystem thisSystem = thisSystemRepository.findThisSystem();
		BigDecimal transferFee = new BigDecimal(money).multiply(thisSystem.getCashFeeRate()).setScale(2,
				RoundingMode.HALF_UP);
		BigDecimal actualCashAmount = new BigDecimal(money).subtract(transferFee).setScale(2, RoundingMode.HALF_UP);

		member.setFlow(member.getFlow() + 1);
		memberRepository.update(member);

		String orderNoStart = DateUtils.getNowStr("yyMMdd") + member.getId();
		String orderNoEnd = String.valueOf(member.getFlow());
		int lenth = thisSystem.getOrderNoLength() - orderNoStart.length() - orderNoEnd.length();
		StringBuffer sb = new StringBuffer("");
		for (int i = 0; i < lenth; i++) {
			sb.append(String.valueOf(StrUtils.getRandomInt()));
		}

		CashApply cashApply = new CashApply();
		cashApply.setCashNo(orderNoStart + sb.toString() + orderNoEnd);
		cashApply.setOpenId(openId);
		cashApply.setCardNo(member.getCardNo());
		cashApply.setCashAmount(new BigDecimal(money));
		cashApply.setStatus(CashApply.STATUS_APPLY);
		cashApply.setTransferFee(transferFee);
		cashApply.setActualCashAmount(actualCashAmount);
		cashApply.setApplyTime(new Date());
		cashApply.setContact(contact);
		cashApply.setRealName(realName);
		cashApply.setAliAccount(aliAccount);
		cashApplyRepository.save(cashApply);
		return cashApply;
	}

	@Override
	public Page<CashApply> findCashApplyPage(Integer pageNo, Integer pageSize, Map<String, Object> searchParams,
			String sortParam, String sortType, Date startTime, Date endTime) {
		return cashApplyRepository.findCashApplyPage(pageNo, pageSize, searchParams, sortParam, sortType, startTime,
				endTime);
	}

	@Override
	public CashApply executeUpdateStatus(Long id, String openId, Integer status) {
		Member member = memberRepository.findMemberByOpenId(openId);
		if (null == member) {
			throw new ServiceException(StatusHouse.STATUS_MEMBER_NOT_EXIST);
		}
		CashApply cashApply = (CashApply) cashApplyRepository.getById(id);
		if (null == cashApply) {
			throw new ServiceException("error", "非法操作");
		}
		if (!openId.equals(cashApply.getOpenId())) {
			throw new ServiceException("error", "非法操作");
		}
		switch (status) {
		case CashApply.STATUS_SH:
			if (cashApply.getStatus() != CashApply.STATUS_APPLY) {
				throw new ServiceException("error", "该提现未处于申请状态");
			}
			cashApply.setStatus(CashApply.STATUS_SH);
			cashApply.setShTime(new Date());
			break;
		case CashApply.STATUS_WTG:
			if (cashApply.getStatus() != CashApply.STATUS_SH) {
				throw new ServiceException("error", "该提现未处于审核状态");
			}
			cashApply.setStatus(CashApply.STATUS_WTG);
			// 退还贝币
			JinBiAccount jinBiAccount = jinBiAccountRepository.findJinBiAccountByCardNoAndOpenId(member.getCardNo(),
					openId);
			boolean isNormal = MD5Utils.verify(jinBiAccount.getBalance().doubleValue() * 10000 + "",
					jinBiAccount.getEncryption());
			if (!isNormal) {
				throw new ServiceException(StatusHouse.STATUS_ACCOUNT_NOT_NORMAL_ERROR);
			}
			JinBiAccountTrace jinBiAccountTrace = new JinBiAccountTrace();
			jinBiAccountTrace.setJinBiAccountId(jinBiAccount.getId());
			jinBiAccountTrace.setChangeType(ChangeType.CASH_FAIL_ADD);
			jinBiAccountTrace.setBeforeValue(jinBiAccount.getBalance());
			jinBiAccountTrace.setChangeValue(cashApply.getCashAmount());
			BigDecimal afterValue = jinBiAccount.getBalance().add(cashApply.getCashAmount());
			jinBiAccountTrace.setAfterValue(afterValue);
			jinBiAccountTrace.setChangeTime(new Date());
			jinBiAccountTrace.setChangeDate(Integer.valueOf(DateUtils.getDateStr(new Date(), "yyyyMMdd")));
			jinBiAccountTraceRepository.save(jinBiAccountTrace);

			jinBiAccount.setBalance(afterValue);
			jinBiAccount.setUpdateTime(new Date());
			jinBiAccount.setEncryption(MD5Utils.generate(jinBiAccount.getBalance().doubleValue() * 10000 + ""));
			jinBiAccountRepository.update(jinBiAccount);
			break;
		case CashApply.STATUS_FF:
			if (cashApply.getStatus() != CashApply.STATUS_SH) {
				throw new ServiceException("error", "该提现未处于审核状态");
			}
			cashApply.setStatus(CashApply.STATUS_FF);
			cashApply.setToAccountTime(new Date());
			break;
		}
		cashApplyRepository.update(cashApply);
		return cashApply;
	}

	@Override
	public List<CashApply> findCashApplyPageByOpenId(String openId, int pageIndex, int pageSize) {
		return cashApplyRepository.findCashApplyPageByOpenId(openId, pageIndex, pageSize);
	}

	@Override
	public CashApply executeUpdate(CashApply cashApply) {
		cashApplyRepository.update(cashApply);
		return cashApply;
	}

	@Override
	public CashApply findById(Long id) {
		return (CashApply) cashApplyRepository.getById(id);
	}

	@Override
	public BigDecimal findMemberTotalCashAmount(String openId, String cardNo) {
		return cashApplyRepository.findMemberTotalCashAmount(openId, cardNo);
	}

}
